
<script lang="tsx">
import { defineComponent, ref, watch, onUnmounted } from 'vue';
import { ElMessage } from 'element-plus';
import { Film, Play, CircleCheck } from '@vben/icons';
import { $t } from '@vben/locales';
import { obsUpload, obsDownload } from '#/utils/obs';

export default defineComponent({
  name: 'FileVideo',
  components: {
    Film,
    Play,
    CircleCheck
  },
  props: {
    uploadKey: {
      type: Number,
      default: 0,
    },
    modelValue: {
      type: String,
      default: ''
    },
    // 用于回显的文件信息
    fileInfo: {
      type: String,
      default: ''
    },
    fileType: {
      type: String,
      default: 'vid'
    }
  },
  emits: ['update:modelValue', 'change'],
  setup(props, { emit }) {
    const uploadRef = ref();
    const fileList = ref<Array<any>>([]);
    const currentVideo = ref<any>(null);

    // 判断是否为视频文件
    const isVideoFile = (fileName: string) => {
      const videoExtensions = ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv', '.webm'];
      const ext = fileName.toLowerCase().split('.').pop();
      return videoExtensions.some(extension => fileName.toLowerCase().endsWith(extension));
    };

    // 监听 modelValue 变化，用于回显
    watch(() => props.modelValue, (newValue) => {
      if (newValue && props.fileInfo && isVideoFile(newValue)) {
        // 如果有文件信息，设置回显
        console.log('newValue', newValue)
        // 通过obs下载文件流获取视频URL
        obsDownload({
          Key: newValue
        }, (err: any, result: any) => {
          if (err) {
            console.error('获取视频文件失败:', err);
            return;
          }

          // 创建视频Blob URL
          const content = result.InterfaceResult.Content as ArrayBuffer;
          const blob = new Blob([content], {
            type: 'video/mp4'
          });
          const videoUrl = window.URL.createObjectURL(blob);

          currentVideo.value = {
            name: props.fileInfo || 'video.mp4',
            url: videoUrl,
            isLocal: false,
            obsKey: newValue
          };
          
          // 更新 fileList
          fileList.value = [{
            name: currentVideo.value.name,
            url: currentVideo.value.url,
            status: 'success'
          }];
        });
      } else {
        // 清空
        currentVideo.value = null;
        fileList.value = [];
      }
    }, { immediate: true });

    // 文件上传前的验证
    const beforeVideoUpload = (file: File) => {
      // 检查文件类型
      const isVideo = file.type.startsWith('video/');
      if (!isVideo) {
        ElMessage.error($t('competition.newsMgr.videoFormatError'));
        return false;
      }

      // 检查文件大小 (50MB)
      const isLt50M = file.size / 1024 / 1024 < 50;
      if (!isLt50M) {
        ElMessage.error($t('competition.newsMgr.videoSizeError'));
        return false;
      }

      return true;
    };

    // 视频上传处理
    const handleVideoUpload = async (options: any) => {
      const file = options.file;

      try {
        // 使用 obs 上传
        obsUpload({
          Key: file.name,
          SourceFile: file
        }, (err: any, result: any, path?: string) => {
          if (err) {
            ElMessage.error($t('competition.newsMgr.videoUploadError'));
            return;
          }

          if (path) {
            // 清理本地预览URL
            if (currentVideo.value && currentVideo.value.isLocal) {
              URL.revokeObjectURL(currentVideo.value.url);
            }
            
            // 通过obs下载文件流获取视频URL
            obsDownload({
              Key: path
            }, (err: any, result: any) => {
              if (err) {
                console.error('获取视频文件失败:', err);
                ElMessage.error($t('competition.newsMgr.videoUploadError'));
                return;
              }

              // 创建视频Blob URL
              const content = result.InterfaceResult.Content as ArrayBuffer;
              const blob = new Blob([content], {
                type: 'video/mp4'
              });
              const videoUrl = window.URL.createObjectURL(blob);

              // 更新文件信息
              currentVideo.value = {
                name: file.name,
                url: videoUrl,
                size: file.size,
                isLocal: false,
                obsKey: path // 保存obs key用于后续操作
              };
              
              // 更新 fileList
              fileList.value = [{
                name: file.name,
                url: videoUrl,
                status: 'success'
              }];

              // emit 更新值
              emit('update:modelValue', path);
              emit('change', {
                name: file.name,
                url: videoUrl,
                size: file.size,
                key: path
              });

              ElMessage.success($t('competition.newsMgr.videoUploadSuccess'));
            });
          }
        });
      } catch (error) {
        console.error('视频上传失败:', error);
        ElMessage.error($t('competition.newsMgr.videoUploadError'));
      }
    };

    // 上传成功回调
    const handleVideoUploadSuccess = (response: any, file: any) => {
      console.log('视频上传成功:', response);
    };

    // 上传失败回调
    const handleVideoUploadError = (error: any) => {
      console.error('视频上传失败:', error);
      ElMessage.error($t('competition.newsMgr.videoUploadError'));
    };

    // 文件数量超出限制
    const handleVideoUploadExceed = (files: any) => {
      ElMessage.error($t('competition.newsMgr.videoExceedError'));
    };

    // 移除文件
    const handleVideoRemove = () => {
      // 清理URL（包括本地预览和obs下载的Blob URL）
      if (currentVideo.value && currentVideo.value.url) {
        URL.revokeObjectURL(currentVideo.value.url);
      }
      currentVideo.value = null;
      fileList.value = [];
      emit('update:modelValue', '');
      emit('change', null);
    };

    // 格式化文件大小
    const formatFileSize = (bytes: number) => {
      if (bytes === 0) return '0 B';
      const k = 1024;
      const sizes = ['B', 'KB', 'MB', 'GB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    };

    const handleVideoChange = (file: any) => {
      console.log('file', file)
      // 在上传过程中显示本地视频预览
      if (file.raw) {
        const localUrl = URL.createObjectURL(file.raw);
        currentVideo.value = {
          name: file.name,
          url: localUrl,
          size: file.size,
          isLocal: true // 标记为本地预览
        };
      }
    };

    // 组件销毁时清理URL
    onUnmounted(() => {
      if (currentVideo.value && currentVideo.value.url) {
        URL.revokeObjectURL(currentVideo.value.url);
      }
    });

    return {
      uploadRef,
      fileList,
      currentVideo,
      isVideoFile,
      beforeVideoUpload,
      handleVideoUpload,
      handleVideoUploadSuccess,
      handleVideoUploadError,
      handleVideoUploadExceed,
      handleVideoRemove,
      formatFileSize,
      handleVideoChange
    };
  }
});
</script>
<template>
  <div class="video-upload-container">
    <div v-if="currentVideo" class="video-preview">
      <video :src="currentVideo.url" class="video-player" controls preload="metadata">
      </video>
    </div>
    <div class="video-upload flex-shrink-0">
      <el-upload :key="uploadKey" type="picture-card" class="video-upload-card flex-shrink-0" :class="{ 'video-upload-card-active': currentVideo }" ref="uploadRef" action="#" :file-list="fileList" :limit="1"
        accept=".mp4,.avi,.mov,.wmv,.flv" :before-upload="beforeVideoUpload" :on-success="handleVideoUploadSuccess"
        :on-error="handleVideoUploadError" :on-exceed="handleVideoUploadExceed" :http-request="handleVideoUpload"
        :on-remove="handleVideoRemove" :on-change="handleVideoChange" :show-file-list="true">
        <div class="upload-area">
          <el-icon class="upload-icon">
            <Film />
          </el-icon>
          <div class="upload-text">{{ $t('competition.newsMgr.uploadVideo') }}</div>
        </div>
        <template #tip>
          <div class="upload-tip">
            {{ $t('competition.newsMgr.videoUploadTip') }}
          </div>
        </template>
      </el-upload>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.video-upload-container {
  display: flex;
  align-items: top;
  .video-preview {
    width: 300px;
    height: 150px;
    margin-right: 30px;
    flex-shrink: 0;
  }
  .video-upload-card {
    display: flex;
    align-items: top;
    justify-content: start;
    :deep(.upload-area) {
      width: 300px;
      height: 150px;
      margin-top: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      border: solid 1px #DCDFE6;
      border-radius: 4px;
      cursor: pointer;
      margin-right: 30px;
    }
  }
  .video-upload-card-active {
    display: block;
    :deep(.upload-area) {
      display: none;
    }
    :deep(.el-upload--text) {
      display: none;
    }
    :deep(.el-upload-list.el-upload-list--text) {
      max-width: 360px;
    }
  }
}
</style>
